<template>
  <lay-card>
    <lay-row space="20">
      <lay-col md="0" style="display: none">
        <lay-switch
            v-model="saveFlag"
            onswitch-text="启用缓存"
            unswitch-text="关闭缓存"
            style="margin-top: 10px"
            @click="clearLinks"
        ></lay-switch>
      </lay-col>
      <lay-col md="18">
        <lay-input
          v-model="queryName"
          :allow-clear="true"
          @clear="clearAndGetLinks"
          size="sm"
          placeholder="请输入查询，区分大小写"
          @change="filterDbTrees"
        >
          <template #suffix>
            <lay-icon type="layui-icon-search" @click="filterDbTrees" size="sm"></lay-icon>
          </template>
        </lay-input>
      </lay-col>
      <lay-col md="4">
        <lay-button type="normal" @click="insertTable" size="sm" v-if="showCheckbox">确定</lay-button>
      </lay-col>
      <lay-col md="1">
        <lay-icon type="layui-icon-close" @click="cancelCheck" size="sm" v-if="showCheckbox"></lay-icon>
      </lay-col>
    </lay-row>
    <lay-row space="5">
      <lay-line @click="refreshLinks">
        <span>数据源</span>
        <lay-icon type="layui-icon-refresh-one" size="sm" style="margin-left: 5px"></lay-icon>
      </lay-line>
    </lay-row>
    <lay-row space="20">
      <lay-col md="24">
        <lay-scroll :height="scrollHeight" :style="{width: showCheckbox === true ? '480px': '550px'}">
          <lay-tree
            ref="linkTressRef"
            v-model:data="dataLinks"
            height="100%"
            :onlyIconControl="onlyIconControl"
            :showLine="showLine"
            :collapse-transition="true"
            :showCheckbox="showCheckbox"
            :checkStrictly="checkStrictly"
            v-model:checkedKeys="checkedKeys"
            v-model:expandKeys="expandKeys"
            :tail-node-icon="false"
            style="max-width: 350px"
          >
            <template #title="{ data }">
              <lay-row space="10">
                <lay-col md="24">
                  <a size="md" @click="queryDBOrTable(data)">
                    <lay-icon
                        type="layui-icon-unlink"
                        size="sm"
                        v-if="data.type==='db_link' && data.children.length === 0"
                        style="color: royalblue;font-size: 14px"
                    ></lay-icon>
                    <lay-icon
                        type="layui-icon-layer"
                        size="sm"
                        v-if="data.type==='db_base'"
                        style="color: royalblue;font-size: 14px"
                    ></lay-icon>
                    <lay-icon
                        type="layui-icon-table"
                        size="sm"
                        v-if="data.type==='db_table'"
                        style="color: turquoise;"
                    ></lay-icon>
                    <span>{{data.title}}</span>
                  </a>
<!--                  <a style="color: #3575ef;margin-left: 15px" v-if="data.type === 'db_base' && data.children.length>0">-->
<!--                    <lay-icon-->
<!--                      type="layui-icon-left"-->
<!--                      size="sm"-->
<!--                      style="font-size: 14px"-->
<!--                      @click="loadNextTable(data, 'left')"-->
<!--                    ></lay-icon>-->
<!--                    <a @click="loadNextTable(data, 'right')" style="color: #3575ef;margin-left: 5px">-->
<!--                      <lay-icon-->
<!--                        type="layui-icon-right"-->
<!--                        size="sm"-->
<!--                        style="font-size: 14px"-->
<!--                      ></lay-icon>-->
<!--                      <span v-if="data.more">more...{{data.more}}</span>-->
<!--                    </a>-->
<!--                  </a>-->
                  <a v-if="!showCheckbox">
                    <lay-icon
                      type="layui-icon-addition"
                      v-if="data.type === 'db_root'"
                      @click="addDBType(data)"
                      style="margin-left: 10px"
                    ></lay-icon>
                    <lay-dropdown trigger="hover" updateAtScroll>
                      <lay-icon
                        type="layui-icon-more"
                        v-if="data.type === 'db_type' || data.type === 'db_link'"
                        style="margin-left: 5px"
                      ></lay-icon>
                      <template #content>
                        <lay-card>
                          <lay-row space="10" v-if="data.type == 'db_type'">
                            <lay-col md="22">
                              <lay-dropdown-menu-item @click="addDBSource(data)">
                                <lay-icon type="layui-icon-add-circle"></lay-icon>新增
                              </lay-dropdown-menu-item>
                            </lay-col>
                          </lay-row>
                          <lay-row space="10" v-if="data.type == 'db_link'">
                            <lay-col md="22">
                              <lay-dropdown-menu-item @click="addDBSource(data)">
                                <lay-icon type="layui-icon-edit"></lay-icon>编辑
                              </lay-dropdown-menu-item>
                            </lay-col>
                          </lay-row>
                          <lay-row space="10">
                            <lay-col md="22">
                              <lay-dropdown-menu-item @click="deleteNode(data)">
                                <lay-icon type="layui-icon-delete"></lay-icon>删除
                              </lay-dropdown-menu-item>
                            </lay-col>
                          </lay-row>
                        </lay-card>
                      </template>
                    </lay-dropdown>
                  </a>
                </lay-col>
              </lay-row>
            </template>
          </lay-tree>
      </lay-scroll>
      </lay-col>
    </lay-row>
    <lay-line></lay-line>
  </lay-card>
</template>

<script lang="ts">
export default {
    name: 'SourcesTree'
}
</script>

<script lang="ts" setup>
import {getCurrentInstance, h, onMounted, onUnmounted, reactive, ref, watch} from 'vue';
import {layer} from "@layui/layui-vue";
import AddDataSource from "./AddDataSource.vue";
import AddSourceType from "./AddSourceType.vue";
import {
  deleteLink,
  getAllLinks,
  queryAllBases,
  queryAllColumnTree,
  queryAllTables
} from "../../api/module/db";
import {TreeService} from "../../store/databases/TreeService";
import {TreeNode} from "../../store/databases/TreeNode";
import {notify} from "../../untils/tip";

let instance = getCurrentInstance();

const {scrollHeight, showCheckbox, target, checkStrictly, checkKeys, setFiledRule} = defineProps({
    scrollHeight: {type: String, default: '700px'},
    showCheckbox: {type: Boolean, default: ref(false)},
    target: {type: String, default: ref('right')},
    checkStrictly: {type: Boolean, default: false},
    checkKeys: {type: Array, default: []},
    setFiledRule: {type: Function}
});


const emit = defineEmits(["insertTables", "cancelCheck"]); //定义一个变量来接收父组件传来的方法

onMounted(() => {
  if(checkStrictly){
    checkedKeys.value = checkKeys;
  }
  getDbTrees();
})

const treeService = new TreeService();
const onlyIconControl = ref(true);
const showLine = ref(false);
const checkedKeys = ref([]);
const expandKeys = ref([]);
const queryName = ref('');
const load_id = ref();

const db_root = reactive({
	title: '数据库连接',
	id: '0',
    spread: true,
    type: 'db_root',
	checked: true,
	children: []
});

const dataLinks: any = ref([]);
const linkTressRef = ref();
const db_lay_id = ref();


// 查询树，筛选树
const filterDbTrees = () => {
    load_id.value = layer.load(1, {time: 20000});
    console.log('filterDbTrees: ' )
    const newTrees = treeService.filterTree(dataLinks.value[0], (node: TreeNode)=>{
      return node.title.includes(queryName.value);});
    console.log(newTrees)
    dataLinks.value = [newTrees];
    layer.close(load_id.value);
};

const clearAndGetLinks = () => {
    dataLinks.value = treeService.getTree();
};

const getDbTrees = async () => {
  const links: any = localStorage.getItem('links');
  // if(links){
  //   const rootTree = JSON.parse(links);
  //   treeService.addRawData(rootTree[0]);
  //   console.log('links local : ', treeService.getTree())
  //   dataLinks.value = rootTree;
  // }else {
  //   await getDBSource();
  // }
  await getDBSource();

};

const refreshLinks = () => {
    localStorage.setItem('sceneTreeExpend', JSON.stringify(expandKeys.value));
    getDBSource();
};

// 记录展开的数组
const setLinkExpand = () => {
  const linksExpend = localStorage.getItem('linksExpend');
  if(linksExpend){
    expandKeys.value = JSON.parse(linksExpend);
  }
}

const getDBSource = async () => {
  dataLinks.value = [];
  treeService.clearTree();
  let {result, status, message} = await getAllLinks();
  if (status === 'success'){
      treeService.addRawData(result);
  }else {
      treeService.addRawData(db_root);
  }
  dataLinks.value = treeService.getTree();
  // setLinkExpand();
}

const clearLinks = () => {
  if(saveFlag.value){
    localStorage.removeItem('links');
  }
};

const insertTable = () => {
  console.log('checkedKeys:', checkStrictly, checkedKeys.value);
  console.log(treeService.getTree());
  if(!checkStrictly){
    // 场景编辑页面，插入表
    const targetTables = treeService.fundTargetTables(checkedKeys.value);
    console.log(targetTables);
    emit('insertTables', targetTables, target);
  }else {
    // 规则列表页面，规则管理数据库场景
    setFiledRule(checkedKeys.value);
  }
};

const cancelCheck = () => {
    emit('cancelCheck');
}

const addDBType = (node: any) => {
  db_lay_id.value = layer.open({
    title: "新增数据库类型",
    area: ['350px','120px'],
    content: h(AddSourceType, {
      parentId: node.id,
      updateRootNode: function (ch_node: any) {
        if (ch_node.id !== '') {
          node.children.push(ch_node);
          treeService.addNode(node.id, ch_node);
        }else {
          layer.msg('添加节点失败，节点id为空！')
        }
        layer.close(db_lay_id.value);
      }
    }),
  })
};

const queryDBOrTable = async (node: any) => {
  load_id.value = layer.load(1, {time: 20000});
  console.log('queryDBOrTable:', node)
  // node.spread = !node.spread;
  if(node.type === 'db_link'){
    let {result, status, message} = await queryAllBases({id: node.id});
    if(status === 'success'){
      node.children = result;
      treeService.addNodeList(node.id, result);
      if(node.children) {
          node.spread = !node.spread;
          treeService.updateNode(node.id, node);
      }
    }else {
      notify(status, message)
    }
  }else if(node.type === 'db_base'){
    let {result, status, message} = await queryAllTables({db_id: node.db_id, database: node.title});
    if(status === 'success'){
      treeService.addNodeList(node.id, result);
      node.children = result;
      // loadNextTable(node, 'right');
      if(node.children) {
          node.spread = !node.spread;
          treeService.updateNode(node.id, node);
      }
      console.log("expandKeys:", expandKeys.value);
    }else {
      notify(status, message);
    }
  }else if(node.type === 'db_table' && !showCheckbox){
    console.log('查看表的字段信息或表数据');
    node.children = [];
    treeService.updateNode(node.id, node);
    instance?.proxy?.$Bus.emit('on-table', node);
  }
  else if(node.type === 'db_table' && showCheckbox){
    let {result, status, message} = await queryAllColumnTree({db_id: node.db_id, database: node.database, table: node.title});
    if(status === 'success'){
      treeService.addNodeList(node.id, result);
      node.children = result;
      console.log(node.spread)
      // loadNextTable(node, 'right');
      // node.spread = !node.spread;
    }else {
      notify(status, message);
    }
  }
  dataLinks.value = treeService.getTree();
  layer.close(load_id.value);
};

// 分批加载子节点
const loadNextTable = (node: any, pos: string = 'left', step: number = 20): TreeNode[]|undefined => {
  let startIndex: number = 0;
  const child = node.children;
  const targetParent = treeService.fundTargetNode(node.id);
  if(child.length === 0){
    startIndex = 0;
  }else {
    if(pos === 'left'){
      const firstNode = child[0];
      startIndex = targetParent?.children.indexOf(firstNode)-10;
    }else {
      const lastNode = child[child.length-1];
      startIndex = targetParent.children.indexOf(lastNode)+10;
    }
  }
  console.log('loadNextTable params : ', node.id, startIndex, step, targetParent);
  const nodes = ref([]);
  if(targetParent){
    targetParent.children?.forEach((unit: TreeNode, index: number)=>{
      if(index>=startIndex && (startIndex+step)>index){
        nodes.value.push(unit)
      }
    })
  }
  node.more = targetParent?.children?.length - startIndex - step;
  console.log('loadNextTable:', nodes.value)
  if(nodes.value.length > 0){
    node.children = nodes.value;
  }
  return nodes.value;
};


const addDBSource = (node: any) => {
  console.log('addDBSource:')
  console.log(node);
  const db_link = reactive({flag: '', parent_id: '', id: '', name: '', type: '', db_type: '', children: []})
  console.log(db_link)
  const title_name = ref('');
  if (node.type === 'db_type') {
    db_link.flag = 'add';
    db_link.type = 'db_link';
    db_link.db_type = node.title;
    db_link.parent_id = node.id;
    title_name.value = "新增数据库连接";
  }else {
    db_link.id = node.id;
    db_link.name = node.title;
    db_link.type = node.type;
    db_link.flag = 'update';
    title_name.value = "更新数据库连接";
  }
  console.log(db_link)
  db_lay_id.value = layer.open({
    type: 'page',
    title: title_name.value,
    area: ['400px','650px'],
    content: h(AddDataSource, {
      db_link,
      updateData: function (node_dict: any) {
        console.log('addDBSource updateData:')
        console.log(node_dict)
        if(node_dict.flag === 'add'){
          node.children.push(node_dict);
          treeService.addNode(db_link.id, node_dict);
        }else if(node_dict.flag === 'update'){
          node.title = node_dict.name;
          treeService.updateNode(db_link.id, node_dict);
        }else {
          layer.msg('不确定的操作类型！')
        }
        layer.close(db_lay_id.value);
      },
      closeLayUi: function (){
        layer.close(db_lay_id.value);
      }
    }),
  })
};

const deleteNodeOperate = async (node: any) => {
  let {result, status, message} = await deleteLink({id: node.id, type: node.type});
  if(status === 'success'){
    treeService.removeNode(node.id);
    let parentNode = node.parentNode;
    console.log(parentNode)
    // 新增加后节点前端挂上去的，与从后台查询的稍有区别。此类直接删除会有异常，无法移除；故去请求一次后台数据刷新
    if(parentNode){
      const index = parentNode.children.indexOf(node);
      parentNode.children.splice(index, 1);
    }else {
      await getDBSource();
    }
  }else {
    layer.msg(message);
  }
};

const deleteNode = (node: any) => {
  console.log('deleteNode')
  console.log(node)
  layer.confirm('确认要删除该节点么？', {
    btn: [
        {text:'确认', callback: (id: any) => {
            deleteNodeOperate(node);
            layer.close(id); }
        },
        {text:'取消', callback: (id: any) => {
          layer.close(id);}
        }
    ]
  })
};

// const saveFlag = ref(true);
//
// // 关闭组件时保存当前
// onUnmounted(() => {
//   if(!saveFlag.value){
//     localStorage.removeItem('links');
//   }else {
//     localStorage.setItem('links', JSON.stringify(treeService.getTree()));
//     localStorage.setItem('linksExpend', JSON.stringify(expandKeys.value))
//   }
// })

</script>

<style>

</style>